﻿using System;
using Amazon.SQS;
using Amazon.SimpleNotificationService;
using Autofac;
using ShuttleBus.Serialization;
using ShuttleBus.Subscriptions;
using ShuttleBus.Threading;
using ShuttleBus.Transports.AmazonSqs.Clients;

namespace ShuttleBus.Transports.AmazonSqs
{
    [TransportModule("sqs")]
    public class SqsModule : Module
    {
        private readonly int _threadCount;
        private readonly Uri _transportEndpoint;
        private readonly string _awsAccessKey;
        private readonly string _awsSecretKey;
        private readonly int _secondsToProcessMessage;
        private readonly int _maxRetries;
        private readonly Serializer _serializer;

        public SqsModule(int threadCount, Uri transportUri, string awsAccessKey, string awsSecretKey, int secondsToProcessMessage, int maxRetries, Serializer serializer)
        {
            _threadCount = threadCount;
            _transportEndpoint = transportUri;
            _awsAccessKey = awsAccessKey;
            _awsSecretKey = awsSecretKey;
            _secondsToProcessMessage = secondsToProcessMessage;
            _maxRetries = maxRetries;
            _serializer = serializer;
        }

        protected override void Load(ContainerBuilder builder)
        {
            switch (_serializer)
            {
                    case Serializer.Xml:
                    builder.Register(c => new XmlSerializer())
                        .As<ISerializer>()
                        .InstancePerLifetimeScope();
                    break;
                    case Serializer.Json:
                default:
                    builder.Register(c => new JsonSerializer())
                        .As<ISerializer>()
                        .InstancePerLifetimeScope();
                    break;
            }

            builder.Register(c => new AmazonSimpleNotificationServiceClient(_awsAccessKey, _awsSecretKey))
                .As<AmazonSimpleNotificationService>()
                .InstancePerLifetimeScope();

            builder.Register(c => new AmazonSQSClient(_awsAccessKey, _awsSecretKey))
                .As<AmazonSQS>()
                .InstancePerLifetimeScope();

            builder.Register(c => new SnsWrapper(c.Resolve<AmazonSimpleNotificationService>()))
                .As<ISnsClient>()
                .InstancePerLifetimeScope();
            
            builder.Register(c => new SqsWrapper(c.Resolve<AmazonSQS>()))
                .As<ISqsClient>()
                .InstancePerLifetimeScope();

            builder.Register(c => new SnsSubscriptionRepository(c.Resolve<ISnsClient>(),
                                                                           c.Resolve<ISqsClient>(),
                                                                           _transportEndpoint))
                .As<ISubscriptionRepository>()
                .InstancePerLifetimeScope();

            builder.Register(c => new ThreadFactory())
                .As<IThreadFactory>()
                .InstancePerLifetimeScope();

            builder.Register(
                c => new SqsEndpoint(_transportEndpoint, () => new AmazonSQSClient(_awsAccessKey, _awsSecretKey), _secondsToProcessMessage))
                .As<IEndpoint>()
                .InstancePerLifetimeScope();

            builder.Register(c => new SqsTransport(c.Resolve<IEndpoint>(),
                                                   c.Resolve<ISerializer>(),
                                                   _threadCount,
                                                   c.Resolve<ICreateStreams>(),
                                                   c.Resolve<IReadStreams>(),
                                                   _maxRetries
                                      ))
                .As<ITransport>()
                .InstancePerLifetimeScope();
        }
    }
}